import theAxios from 'axios'
import router from '@/router'
import Notify from '@/ui/hint'
import { getToken, removeToken, setToken } from './token'
import { refreshTokenApi } from '@/api'

const axios = theAxios.create({
  baseURL: 'http://geek.itheima.net',
  timeout: 20000 // 20秒超时时间 超过20秒判定超时
})

// 添加请求拦截器
axios.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么  null有值 undefined 未定义
    // ?. 可选链操作符 如果前面对象里没有length(undefined)则整个表达式原地返回一个 undefined
    // 如果getToken()在原地有值token字符串， 才能调用length 获取长度
    // getToken() 也能直接写 如果getToken()返回为空 if 直接不执行
    if (getToken()?.length > 0 && config.headers.Authorization === undefined) {
      // 要执行某些操作(点赞 举报等) 要向后台发送本地存储的token验证身份 否则后台会返回 401 错误拦截器要拦截执行跳转登录
      config.headers.Authorization = `Bearer ${getToken()}` // 请求头 向后台发送本地存储的token值
    }
    return config
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

// 添加响应拦截器
axios.interceptors.response.use(
  (response) => {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response
  },
  //  这里会拦截以 4 5 开头的状态码
  async (error) => {
    if (error.request.status === 401) {
      // 401 表示 token值过期
      removeToken() // 先删除token 才能让路由判断失效，进行跳转
      console.log(error)
      const res = await refreshTokenApi()
      // 重新设置本地token
      setToken(res.data.data.token)
      // 将重新获取的token 添加到请求头中
      error.config.headers.Authorization = `Bearer ${res.data.data.token}`
      // 重新发起请求
      return axios(error.config)
      // token 过期强制跳转登录 用户有感知
      // router.replace('/login') // 用路由跳转到登录页面 这里的this 是undefined
    } else if (
      error.response.status === 500 &&
      error.config.method === 'put' &&
      error.config.url === '/v1_0/authorizations'
    ) {
      localStorage.clear()
      Notify({ type: 'warning', message: '账号登录过期' })
      router.replace('/login')
    }

    return Promise.reject(error)
  }
)

// 当 外面不传值时 method = 'GET', params = {}, data = {}, headers = {} 默认赋值
export default ({
  url,
  method = 'GET',
  params = {},
  data = {},
  headers = {}
}) =>
  axios({
    // 对象解构赋值写法
    url, //  不用 return axios 箭头函数不用写括号和 return 原地返回一个 Promise 对象
    method,
    params,
    data,
    headers
  })
// 以后换库, 只需要改这里, 逻辑页面不用动, 保证代码的复用性和独立性(高内聚低耦合)
// return new Promise((resolve, reject) => {
//     判断如果 params有值 需要自己写js代码 把params 对象里的key和value拼接到url上
//     $.ajax({
//         url: url,
//         type: method,
//         data: data,
//         header: headers
//        success: (res) => {
//             resolve(res)
//         },
//         error: (err) => {
//             reject(err)
//         }
//     })
// }
